/**
 * AbstractSaver.java ##copyright## This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option) any later version.
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details. You should have received a copy of the GNU Lesser
 * General Public License along with this library; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 * 
 * @author ##author##
 * @modified ##date##
 * @version ##version##
 */
package fiveagon.saver;

import java.io.File;

import processing.core.PApplet;
import fiveagon.util.Time;

/**
 * Abstract implementation of <code>interface Saver</code>.
 * <p>
 * This class makes the process of saving images even easier than it already is by providing
 * consistent, yet dynamic filenames with a time stamp. It also makes the process of recording
 * high-quality visual output as easy as it needs to be when starting a new sketch.
 * </p>
 * <p>
 * This class is designed with the <a
 * href="http://en.wikipedia.org/wiki/Template_method_pattern">Template method pattern</a> in mind.
 * Subclasses will implement two abstract methods plus an optional third. These methods are
 * <strong>not</strong> public; they will be called by the methods of the <code>Saver</code>
 * interface.
 * </p>
 * 
 * <pre>
 * 
 * protected String abstractSave() {
 * }
 * 
 * protected abstract String abstractBeginRecord();
 * 
 * protected abstract void abstractEndRecord();
 * </pre>
 */
public abstract class AbstractSaver implements Saver {
  private static final String DEFAULT_SAVE_FOLDER = "print";

  protected final PApplet parent;
  private final String savePrefix;

  private boolean isRecording = false;

  /**
   * Constructor for subclasses.
   * 
   * @param parent A reference to the <code>PApplet</code>. Usually the reference is passed using
   *        <code>this</code>.
   * @param userSavePrefix The desired filename prefix. If the prefix contains a folder separator,
   *        the desired folder is used. Otherwise, a default folder "print" will be used.
   */
  public AbstractSaver(PApplet parent, String userSavePrefix) {
    this.parent = parent;
    this.savePrefix = createSavePrefix(userSavePrefix);
  }

  private String createSavePrefix(String userSavePrefix) {
    if (userSavePrefix.contains(File.separator)) {
      return userSavePrefix;
    } else {
      return DEFAULT_SAVE_FOLDER + File.separator + userSavePrefix;
    }
  }

  public final void save() {
    String filename = abstractSave();
    System.out.println("save: " + filename);
  }

  public final void saveRecord() {
    isRecording = true;
  }

  public final void beginRecord() {
    if (isRecording) {
      String filename = abstractBeginRecord();
      System.out.println("saveRecord: " + filename + " ...");
    }
  }

  public final void endRecord() {
    if (isRecording) {
      abstractEndRecord();
      isRecording = false;
      System.out.println("file Recorded!");
    }
  }

  /**
   * Answers the question of whether or not this <code>Saver</code> is recording.
   * 
   * @return <code>true</code>, if this <code>Saver</code> is recording
   */
  public final boolean isRecording() {
    return isRecording;
  }

  /**
   * Gets the prefix that this <code>Saver</code> will use when creating file names.
   * 
   * @return the prefix (including the folder name) of the files that will be created by this
   *         <code>Saver</code>
   * @see PApplet#println(Object)
   * @see System#out
   */
  @Override
  public String toString() {
    return savePrefix;
  }

  /**
   * Creates a dynamic filename.
   * 
   * @param fileExtension the desired file extension, usually in the form ".xxx"
   * @return the newly created filename
   */
  protected String createFilename(String fileExtension) {
    return savePrefix + Time.stamp() + fileExtension;
  }

  /**
   * Saves an image of the sketch window. This is also the general form for implementing
   * abstractBeginRecord() down below.
   * 
   * @return the filename of the image
   */
  protected String abstractSave() {
    String filename = createFilename(".png");
    parent.save(filename);

    return filename;
  }

  /**
   * Initializes the High-Quality recording.
   * 
   * @return the filename of the recording
   */
  protected abstract String abstractBeginRecord();

  /**
   * Finishes the High-Quality recording.
   */
  protected abstract void abstractEndRecord();
}
